home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
emulator
/
bsvc-1.000
/
bsvc-1
/
bsvc-1.0.4
/
src
/
Assemblers
/
68kasm
/
directive.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-26
|
10KB
|
436 lines
/******************************************************************************
* $Id: directive.c,v 1.1 1994/08/29 23:56:47 bmott Exp $
******************************************************************************
*
*
* DIRECTIVE.C
* Directive Routines for 68000 Assembler
*
* Description: The functions in this file carry out the functions of
* assembler directives. All the functions share the same
* calling sequence:
*
* general_name(size, label, op, errorPtr)
* int size;
* char *label, *op;
* int *errorPtr;
*
* The size argument contains the size code that was
* specified with the instruction (using the definitions
* in ASM.H) or 0 if no size code was specified. The label
* argument is a pointer to a string (which may be empty)
* containing the label from the line containing the
* directive. The op argument is a pointer to the first
* non-blank character after the name of the directive,
* i.e., the operand(s) of the directive. The errorPtr
* argument is used to return a status via the standard
* mechanism.
*
* Author: Paul McKee
* ECE492 North Carolina State University
*
* Date: 12/13/86
*
* Copyright 1990-1991 North Carolina State University. All Rights Reserved.
*
******************************************************************************
* $Log: directive.c,v $
* Revision 1.1 1994/08/29 23:56:47 bmott
* Initial revision
*
*****************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include "asm.h"
extern int loc;
extern char pass2, endFlag, listFlag;
symbolDef *define();
extern char *listPtr; /* Pointer to buffer where listing line is assembled
(Used to put =XXXXXXXX in the listing for EQU's and SET's */
/***********************************************************************
*
* Function org implements the ORG directive.
*
***********************************************************************/
org(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int newLoc;
char backRef;
char *eval();
if (size)
NEWERROR(*errorPtr, INV_SIZE_CODE);
if (!*op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
op = eval(op, &newLoc, &backRef, errorPtr);
if (*errorPtr < SEVERE && !backRef) {
NEWERROR(*errorPtr, INV_FORWARD_REF);
}
else if (*errorPtr < ERROR) {
if (isspace(*op) || !*op) {
/* Check for an odd value, adjust to one higher */
if (newLoc & 1) {
NEWERROR(*errorPtr, ODD_ADDRESS);
newLoc++;
}
loc = newLoc;
/* Define the label attached to this directive, if any */
if (*label)
define(label, loc, pass2, errorPtr);
/* Show new location counter on listing */
listLoc();
}
else
NEWERROR(*errorPtr, SYNTAX);
}
}
/***********************************************************************
*
* Function end implements the END directive.
*
***********************************************************************/
End(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
if (size)
NEWERROR(*errorPtr, INV_SIZE_CODE);
endFlag = TRUE;
}
/***********************************************************************
*
* Function equ implements the EQU directive.
*
***********************************************************************/
equ(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int value;
char backRef;
char *eval();
if (size)
NEWERROR(*errorPtr, INV_SIZE_CODE);
if (!*op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
op = eval(op, &value, &backRef, errorPtr);
if (*errorPtr < SEVERE && !backRef) {
NEWERROR(*errorPtr, INV_FORWARD_REF);
}
else if (*errorPtr < ERROR)
if (isspace(*op) || !*op)
if (!*label) {
NEWERROR(*errorPtr, LABEL_REQUIRED);
}
else {
define(label, value, pass2, errorPtr);
if (pass2 && listFlag && *errorPtr < MINOR) {
sprintf(listPtr, "=%08X ", value);
listPtr += 10;
}
}
else
NEWERROR(*errorPtr, SYNTAX);
}
/***********************************************************************
*
* Function set implements the SET directive.
*
***********************************************************************/
set(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int value, error;
char backRef;
symbolDef *symbol;
char *eval();
if (size)
NEWERROR(*errorPtr, INV_SIZE_CODE);
if (!*op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
error = OK;
op = eval(op, &value, &backRef, errorPtr);
if (*errorPtr < SEVERE && !backRef) {
NEWERROR(*errorPtr, INV_FORWARD_REF);
}
if (*errorPtr > ERROR)
if (isspace(*op) || !*op)
if (!*label) {
NEWERROR(*errorPtr, LABEL_REQUIRED);
}
else {
error = OK;
symbol = define(label, value, pass2, &error);
if (error == MULTIPLE_DEFS)
if (symbol->flags & REDEFINABLE)
symbol->value = value;
else {
NEWERROR(*errorPtr, MULTIPLE_DEFS);
return;
}
symbol->flags |= REDEFINABLE;
if (pass2 & listFlag) {
sprintf(listPtr, "=%08X ", value);
listPtr += 10;
}
}
else
NEWERROR(*errorPtr, SYNTAX);
}
/***********************************************************************
*
* Function dc implements the DC directive.
*
***********************************************************************/
dc(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int outVal;
char backRef;
char string[260], *p, *collect(), *eval();
if (size == SHORT) {
NEWERROR(*errorPtr, INV_SIZE_CODE);
size = WORD;
}
else if (!size)
size = WORD;
/* Move location counter to a word boundary and fix the listing if doing
DC.W or DC.L (but not if doing DC.B, so DC.B's can be contiguous) */
if ((size & (WORD | LONG)) && (loc & 1)) {
loc++;
listLoc();
}
/* Define the label attached to this directive, if any */
if (*label)
define(label, loc, pass2, errorPtr);
/* Check for the presence of the operand list */
if (!*op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
do {
if (*op == '\'') {
op = collect(++op, string);
if (!isspace(*op) && *op != ',') {
NEWERROR(*errorPtr, SYNTAX);
return;
}
p = string;
while (*p) {
outVal = *p++;
if (size > BYTE)
outVal = (outVal << 8) + *p++;
if (size > WORD) {
outVal = (outVal << 16) + (*p++ << 8);
outVal += *p++;
}
if (pass2)
output(outVal, size);
loc += size;
}
}
else {
op = eval(op, &outVal, &backRef, errorPtr);
if (*errorPtr > SEVERE)
return;
if (!isspace(*op) && *op != ',') {
NEWERROR(*errorPtr, SYNTAX);
return;
}
if (pass2)
output(outVal, size);
loc += size;
if (size == BYTE && (outVal < -128 || outVal > 255)) {
NEWERROR(*errorPtr, INV_8_BIT_DATA);
}
else if (size == WORD && (outVal < -32768 || outVal > 65535))
NEWERROR(*errorPtr, INV_16_BIT_DATA);
}
} while (*op++ == ',');
--op;
if (!isspace(*op) && *op)
NEWERROR(*errorPtr, SYNTAX);
}
/**********************************************************************
*
* Function collect parses strings for dc. Each output string
* is padded with four nulls at the end.
*
**********************************************************************/
char *collect(s, d)
char *s, *d;
{
while (*s) {
if (*s == '\'')
if (*(s+1) == '\'') {
*d++ = *s;
s += 2;
}
else {
*d++ = '\0';
*d++ = '\0';
*d++ = '\0';
*d++ = '\0';
return ++s;
}
else
*d++ = *s++;
}
return s;
}
/***********************************************************************
*
* Function dcb implements the DCB directive.
*
***********************************************************************/
dcb(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int blockSize, blockVal, i;
char *eval();
char backRef;
if (size == SHORT) {
NEWERROR(*errorPtr, INV_SIZE_CODE);
size = WORD;
}
else if (!size)
size = WORD;
/* Move location counter to a word boundary and fix the listing if doing
DCB.W or DCB.L (but not if doing DCB.B, so DCB.B's can be contiguous) */
if ((size & (WORD | LONG)) && (loc & 1)) {
loc++;
listLoc();
}
/* Define the label attached to this directive, if any */
if (*label)
define(label, loc, pass2, errorPtr);
/* Evaluate the size of the block (in bytes, words, or longwords) */
op = eval(op, &blockSize, &backRef, errorPtr);
if (*errorPtr < SEVERE && !backRef) {
NEWERROR(*errorPtr, INV_FORWARD_REF);
return;
}
if (*errorPtr > SEVERE)
return;
if (*op != ',') {
NEWERROR(*errorPtr, SYNTAX);
return;
}
if (blockSize < 0) {
NEWERROR(*errorPtr, INV_LENGTH);
return;
}
/* Evaluate the data to put in block */
op = eval(++op, &blockVal, &backRef, errorPtr);
if (*errorPtr < SEVERE) {
if (!isspace(*op) && *op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
/* On pass 2, output the block of values directly
to the object file (without putting them in the listing) */
if (pass2)
for (i = 0; i < blockSize; i++) {
outputObj(loc, blockVal, size);
loc += size;
}
else
loc += blockSize * size;
}
}
/***********************************************************************
*
* Function ds implements the DS directive.
*
***********************************************************************/
ds(size, label, op, errorPtr)
int size;
char *label, *op;
int *errorPtr;
{
int blockSize;
char backRef;
char *eval();
if (size == SHORT) {
NEWERROR(*errorPtr, INV_SIZE_CODE);
size = WORD;
}
else if (!size)
size = WORD;
/* Move location counter to a word boundary and fix the listing if doing
DS.W or DS.L (but not if doing DS.B, so DS.B's can be contiguous) */
if ((size & (WORD | LONG)) && (loc & 1)) {
loc++;
listLoc();
}
/* Define the label attached to this directive, if any */
if (*label)
define(label, loc, pass2, errorPtr);
/* Evaluate the size of the block (in bytes, words, or longwords) */
op = eval(op, &blockSize, &backRef, errorPtr);
if (*errorPtr < SEVERE && !backRef) {
NEWERROR(*errorPtr, INV_FORWARD_REF);
return;
}
if (*errorPtr > SEVERE)
return;
if (!isspace(*op) && *op) {
NEWERROR(*errorPtr, SYNTAX);
return;
}
if (blockSize < 0) {
NEWERROR(*errorPtr, INV_LENGTH);
return;
}
loc += blockSize * size;
}